package com.jiepos.mpos.biz.user.service;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.jiepos.mpos.common.constant.DBConstant.Code;
import com.jiepos.mpos.common.constant.DBConstant.Table;
import com.jiepos.mpos.common.constant.SystemConstant;
import com.jiepos.mpos.common.dao.AppMenuAuthInfDao;
import com.jiepos.mpos.common.dao.AppRoleInfDao;
import com.jiepos.mpos.common.entity.App_Ins_InfEntity;
import com.jiepos.mpos.common.entity.App_MenuAuth_InfEntity;
import com.jiepos.mpos.common.entity.App_Role_InfEntity;
import com.jiepos.mpos.core.entity.Pagination;
import com.jiepos.mpos.core.service.BaseService;
import com.jiepos.mpos.core.util.IDFactoryUtil;

/**
 * @ClassName: AppRoleInfService
 * @Description: 角色管理服务层
 * @author 孙永
 * @date 2017年9月19日 下午3:08:25
 */
@Service
public class AppRoleInfService extends BaseService{

	@Autowired
	private AppRoleInfDao appRoleInfDao;
	@Autowired
	private AppMenuAuthInfDao appMenuAuthInfDao;
	@Autowired
	private AppInsInfService appInsInfService;
	
	public Map<String, Object> getRoleInfPageList(HttpServletRequest request, Pagination pagination, App_Role_InfEntity condition){
		/*组装查询sql*/
		StringBuffer sql = getInitSql("t1").append(",");
		sql.append("t1.role_uuid uuid, t1.role_name, t1.role_desc, t1.ins_uuid,t1.role_tp,")
		.append("t1.role_tp || '-' || t2.code_desc role_tp_desc,")
		.append("nvl2(t3.ins_cd, t3.ins_cd || '-' || t3.ins_cn_nm, '') ins_cn_nm")
		.append(" FROM ")
		.append(Table.T_APP_ROLE_INF).append(" t1")
		.append(" LEFT JOIN ").append(Table.T_APP_CODE_LIST).append(" t2 ON t1.role_tp = t2.code_val and t2.code_tp = '").append(Code.ROLE_TYPE).append("'")
		.append(" LEFT JOIN ").append(Table.T_APP_INS_INF).append(" t3 ON t1.ins_uuid = t3.ins_uuid")
		.append(" where (t1.ins_uuid is null or t1.ins_uuid in (select tt.ins_uuid from T_APP_INS_INF tt start with tt.ins_uuid = ? connect by prior tt.ins_uuid = tt.sup_ins_uuid))");
		/*构造查询条件*/
		List<String> list = new ArrayList<>();
		list.add(String.valueOf(request.getSession().getAttribute(SystemConstant.SESSION_LOGIN_INS_UUID)));
		/*角色名称查询条件*/
		if(StringUtils.isNotEmpty(condition.getRole_name())){
			sql.append(" and t1.role_name like ?");
			list.add("%" + condition.getRole_name() + "%");
		}
		/*角色类型*/
		if(StringUtils.isNotEmpty(condition.getRole_tp())){
			sql.append(" and t1.role_tp = ?");
			list.add(condition.getRole_tp());
		}
		/*机构编码*/
		if(StringUtils.isNotEmpty(condition.getIns_uuid())){
			sql.append(" and t3.ins_cd like ?");
			list.add("%" + condition.getIns_uuid() + "%");
		}
		pagination.setQueryString(sql.toString());
		pagination = getOrderSql(pagination, "t1");
		return appRoleInfDao.getPaginationMap(pagination, "t1", list);
	}
	
	/**
	 * 根据唯一标识查询详情
	 * @param uuid
	 * @return
	 */
	public Map<String, Object> getRoleInfByUuid(String uuid, HttpServletRequest request){
		/*获取登陆人的机构*/
		String insUuid = String.valueOf(request.getSession().getAttribute(SystemConstant.SESSION_LOGIN_INS_UUID));
		App_Ins_InfEntity ins = appInsInfService.getInsInfByUuid(insUuid);
		Map<String, Object> map = new HashMap<String, Object>();
		/*获取父级机构，有，则是非顶级机构，则角色新增页面不展示机构选择框*/
		map.put("supInsUuid", ins.getSup_ins_uuid());
		map.put("INS_UUID", insUuid);
		if (StringUtils.isBlank(uuid)) {
			return map;
		}
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT T.ROLE_UUID, T.INS_UUID, T.ROLE_NAME, T.ROLE_DESC, T.ROLE_TP,")
		.append("T1.INS_CD || '-' || T1.INS_CN_NM INST_NAME")
		.append(" FROM ")
		.append(Table.T_APP_ROLE_INF).append(" T")
		.append(" LEFT JOIN ")
		.append(Table.T_APP_INS_INF).append(" T1")
		.append(" ON T.INS_UUID = T1.INS_UUID")
		.append(" WHERE T.ROLE_UUID = ?");
		List<String> list = new ArrayList<>();
		list.add(uuid);
		List<Map<String, Object>> results = appRoleInfDao.queryForList(getOrderSql(sql.toString(), "T"), list);
		if(results != null){
			map.putAll(results.get(0));
		}
		return map;
	}
	
	/**
	 * 保存角色信息
	 * @param entity
	 * @param map
	 */
	public void saveRoleInf(App_Role_InfEntity entity, Map map){
		entity.setRec_upd_usr_id(String.valueOf(map.get(SystemConstant.SESSION_LOGIN_USER)));
		/*没有选择机构，则是公有角色，反之私有*/
		if(StringUtils.isBlank(entity.getIns_uuid())){
			entity.setRole_tp("1");// 公有角色
		}else{
			entity.setRole_tp("0");
		}
		if (!StringUtils.isBlank(entity.getRole_uuid())) {// 修改角色信息 
			App_Role_InfEntity oldEntity = appRoleInfDao.findByParam("role_uuid", entity.getRole_uuid());
			entity.setRec_upd_ts(new Timestamp(System.currentTimeMillis()));
			entity.setRec_id(oldEntity.getRec_id());
			entity.setRec_crt_ts(oldEntity.getRec_crt_ts());
			entity.setLast_oper_in(SystemConstant.OPER_UPDATE);
			List<String> noChangeList = new ArrayList<>();
			noChangeList.add("role_uuid");
			appRoleInfDao.update(entity, noChangeList);
		} else {// 新增角色信息
			entity.setRec_crt_ts(new Timestamp(System.currentTimeMillis()));
			entity.setRec_upd_ts(new Timestamp(System.currentTimeMillis()));
			entity.setRole_uuid(IDFactoryUtil.getUUID());
			entity.setLast_oper_in(SystemConstant.OPER_ADD);
			appRoleInfDao.save(entity);
		}
	}
	
	/**
	 * 删除方法
	 * @param role_uuids 角色标识字符串
	 */
	public void deleteMenuByIds(String role_uuids) {
		appRoleInfDao.deleteByStatus("role_uuid",role_uuids);
	}
	
	/**
	 * 查询菜单按钮树数据
	 * @return
	 */
	public List<Map<String, Object>> getMenuBtnTree(HttpServletRequest request, int insLevel, String roleUuid, String roleType){
		StringBuffer sql = new StringBuffer();
		List<String> params = new ArrayList<>();
		/*顶级机构*/
		if(insLevel == 1){
			/*查询全部菜单sql*/
			sql.append("SELECT T.MENU_UUID ID, T.MENU_NAME NAME, T.SUP_MENU_UUID PID")
			.append("  FROM ").append(Table.T_APP_MENU_CD).append(" T")
			.append(" WHERE T.REC_ST = ?")
			.append(" START WITH T.SUP_MENU_UUID IS NULL")
			.append(" CONNECT BY PRIOR T.MENU_UUID = T.SUP_MENU_UUID")
			.append(" ORDER BY T.MENU_ORDERS DESC");
			params.add(SystemConstant.NORMAL_STATUS);
		}else{
			sql.append("SELECT MENU_UUID ID, MENU_NAME NAME, SUP_MENU_UUID PID")
			.append("  FROM (SELECT DISTINCT MC.MENU_UUID,")
			.append("                        MC.MENU_NAME,")
			.append("                        MC.SUP_MENU_UUID,")
			.append("                        MC.MENU_ORDERS")
			.append("          FROM ").append(Table.T_APP_MENU_CD).append(" MC")
			.append("         WHERE MC.REC_ST = ?")
			.append("         START WITH MC.MENU_UUID IN")
			.append("                    (SELECT T.MENU_UUID")
			.append("                       FROM ").append(Table.T_APP_MENUAUTH_INF).append(" T")
			.append("                      WHERE T.REC_ST = ?")
			.append("                        AND T.ROLE_UUID = ?)")
			.append("        CONNECT BY PRIOR MC.SUP_MENU_UUID = MC.MENU_UUID)")
			.append(" ORDER BY MENU_ORDERS DESC");
			params.add(SystemConstant.NORMAL_STATUS);
			params.add(SystemConstant.NORMAL_STATUS);
			/*私有角色，则获取登陆人的角色*/
			if("0".equals(roleType)){
				roleUuid = String.valueOf(request.getSession().getAttribute(SystemConstant.SESSION_ROLE_UUID));
			}
			params.add(roleUuid);
		}
		List<Map<String, Object>> menuList = appRoleInfDao.queryForList(sql.toString(), params);
		if(menuList == null || menuList.isEmpty()){
			return menuList;
		}
		
		/*提取菜单唯一标识*/
		StringBuffer menuUuids = new StringBuffer();
		for(Map<String, Object> menu : menuList){
			menuUuids.append("'").append(menu.get("ID")).append("'").append(",");
			menu.put("open", true);
		}
		
		/*组装查询按钮sql*/
		sql = new StringBuffer();
		params.clear();
		if(insLevel == 1){
			sql.append("SELECT MI.BUTTON_UUID ID,")
			.append("       MI.BUTTON_NAME NAME,")
			.append("       MI.MENU_UUID PID,")
			.append("       'true' IS_BUTTON")
			.append("  FROM ").append(Table.T_APP_MENU_CD).append(" T")
			.append("  LEFT JOIN ").append(Table.T_APP_MENUBUTTON_INF).append(" MI")
			.append("    ON T.MENU_UUID = MI.MENU_UUID")
			.append(" WHERE T.REC_ST = MI.REC_ST")
			.append("   AND MI.REC_ST = ?")
			.append(" ORDER BY T.MENU_ORDERS DESC, MI.BUTTON_ORDERS");
			params.add(SystemConstant.NORMAL_STATUS);
		}else{
			String btnSql = "SELECT wm_concat(AUTH_BUTTONS) BUTTONS FROM T_APP_MENUAUTH_INF WHERE ROLE_UUID = ?";
			params.add(roleUuid);
			List<Map<String, String>> btnMaps = appRoleInfDao.queryForList(btnSql, params);
			if(btnMaps != null && !btnMaps.isEmpty()){
				String btns = btnMaps.get(0).get("BUTTONS");
				btns = "'" + btns + "'";
				btns = btns.replaceAll(",", "','");
				/*查询按钮*/
				sql.append("SELECT BUTTON_UUID ID, BUTTON_NAME NAME, MENU_UUID PID, 'true' IS_BUTTON")
				.append("  FROM ").append(Table.T_APP_MENUBUTTON_INF)
				.append(" WHERE BUTTON_UUID IN (").append(btns).append(")")
				.append(" ORDER BY BUTTON_ORDERS");
			}
			params = null;
		}
		List<Map<String, Object>> btnList = appRoleInfDao.queryForList(sql.toString(), params);
		
		/*合并集合结果*/
		menuList.addAll(btnList);
		return menuList;
	}
	
	/**
	 * 保存角色菜单按钮关系
	 * @param menuAuth
	 * @param map
	 */
	public void saveMenuAuth(HttpServletRequest request, String role_uuid, List<App_MenuAuth_InfEntity> menuAuth, Map map){
		if(menuAuth == null){
			menuAuth = new ArrayList<>();
		}
		App_Role_InfEntity role = appRoleInfDao.findByParam("role_uuid", role_uuid);
		if("1".equals(role.getRole_tp())){
			int insLevel = (int)(request.getSession().getAttribute(SystemConstant.SESSION_LOGIN_INS_LEVEL));
			if(1 != insLevel){
				return;
			}
		}
		String sql = "DELETE FROM T_APP_MENUAUTH_INF WHERE ROLE_UUID = ?";
		List<String> param = new ArrayList<>();
		param.add(role_uuid);
		appMenuAuthInfDao.update(sql, param);
		for(App_MenuAuth_InfEntity entity : menuAuth){
			entity.setRec_upd_usr_id(String.valueOf(map.get(SystemConstant.SESSION_LOGIN_USER)));
			entity.setRec_crt_ts(new Timestamp(System.currentTimeMillis()));
			entity.setRec_upd_ts(new Timestamp(System.currentTimeMillis()));
			entity.setMenuauth_uuid(IDFactoryUtil.getUUID());
			entity.setLast_oper_in(SystemConstant.OPER_ADD);
			appMenuAuthInfDao.save(entity);
		}
	}
	
	/**
	 * 根据角色代码查询出所拥有的权限
	 * @param roleUuid 角色代码
	 * @return
	 */
	public String getMenuAuthByRoleId(String roleUuid){
		if(StringUtils.isEmpty(roleUuid)){
			return null;
		}
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT NVL2(AUTH_BUTTONS, AUTH_BUTTONS, MENU_UUID) AUTH")
		.append("  FROM ").append(Table.T_APP_MENUAUTH_INF)
		.append(" WHERE ROLE_UUID = ?");
		List<String> list = new ArrayList<>();
		list.add(roleUuid);
		List<Map<String, Object>> results = appRoleInfDao.queryForList(getOrderSql(sql.toString(), null), list);
		sql = new StringBuffer();
		for(Map<String, Object> map : results){
			sql.append(map.get("AUTH")).append(",");
		}
		return sql.length() > 0 ? sql.substring(0, sql.length()-1) : null;
	}
	
	/**
	 * 根据角色查询出权限url
	 * @param roleUuid 角色代码
	 * @return
	 */
	public List<Map<String, Object>> getMenuUrlByRoleUuid(String roleUuid){
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT MA.AUTH_BUTTONS, M.MENU_URL, M.MENU_URL1, M.MENU_URL2")
		.append("  FROM ").append(Table.T_APP_MENUAUTH_INF).append(" MA,")
		.append(Table.T_APP_MENU_CD).append(" M")
		.append(" WHERE MA.MENU_UUID = M.MENU_UUID")
		.append("   AND MA.ROLE_UUID = ?");
		List<String> list = new ArrayList<>();
		list.add(roleUuid);
		List<Map<String, Object>> result = appMenuAuthInfDao.queryForList(getOrderSql(sql.toString(), "M"), list);
		return result;
	}
	
	/**
	 * 验证角色名称是否存在
	 * @param roleName 角色名称
	 * @param insUuid 角色所属机构
	 * @param request
	 * @return
	 */
	public boolean roleNameIsExist(String roleName, String insUuid, HttpServletRequest request){
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT *")
		.append("  FROM ").append(Table.T_APP_ROLE_INF)
		.append(" WHERE ROLE_NAME = ?")
		.append("   AND (ROLE_TP = '1'")
		.append(" OR INS_UUID = ?)");
		if(StringUtils.isBlank(insUuid)){
			insUuid = String.valueOf(request.getSession().getAttribute(SystemConstant.SESSION_LOGIN_INS_UUID));
		}
		List<App_Role_InfEntity> list = appRoleInfDao.queryForListByParam(sql.toString(), new Object[]{roleName, insUuid});
		if(list == null || list.isEmpty()){
			return false;
		}
		return true;
	}

}
